#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# this lesson is based on python 3

# PIL：Python Imaging Library，已经是Python平台事实上的图像处理标准库了。PIL功能非常强大，但API却非常简单易用。
from PIL import Image

# 打开一个jpg图像文件，注意是当前路径:
im = Image.open('test.jpg')
# 获得图像尺寸:
w, h = im.size
print('original image size: %sx%s'% (w, h))
# 缩放到50%:
im.thumbnail((w//2, h//2))
print('resize image to: %sx%s'% (w//2, h//2))
# 把缩放后的图像用jpeg格式保存:
im.save('thumbnail.jpg', 'jpeg')

from PIL import ImageFilter
# 应用模糊滤镜:
im2 = im.filter(ImageFilter.BLUR)
im2.save('blur.jpg', 'jpeg')

import random
from PIL import ImageDraw, ImageFont
# ImageDraw提供了一系列绘图方法，让我们可以直接绘图。比如要生成字母验证码图片：

def rndChar(): # 随机字母
    return chr(random.randint(65, 90)) # A-Z in unicode: 65-90

def rndColor(): # 随机颜色
    return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255)) # a triple tuple

def rndColor2():
    return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

width = 60 * 4
height = 60
captcha = Image.new('RGB', (width, height), (255, 255, 255))
# 创建Font对象:
font = ImageFont.truetype(r"C:\Windows\Fonts\Arial.ttf", 36)
# 创建Draw对象:
draw = ImageDraw.Draw(captcha)
# 填充每个像素:
for x in range(width):
    for y in range(height):
        draw.point((x,y), fill=rndColor())
# 输出文字:
for t in range(4):
    draw.text((60*t+10, 10), rndChar(), font=font, fill=rndColor2())
# 应用模糊滤镜:
captcha = captcha.filter(ImageFilter.BLUR)
captcha.save('captcha.jpg', 'jpeg')

# 比内置的urllib模块更好的方案是使用requests。它是一个Python第三方库，处理URL资源特别方便

import requests
r = requests.get('https://www.douban.com/')
print(r.status_code)
print(r.text) # print HTML text
# 对于带参数的URL，传入一个dict作为params参数：
r.requests.get('https://www.douban.com/search', params={'q':'python', 'cat':'1001'})
print(r.url) # 实际请求的URL
'https://www.douban.com/search?q=python&cat=1001'

# requests自动检测编码，可以使用encoding属性查看
r.encoding

# 无论响应是文本还是二进制内容，我们都可以用content属性获得bytes对象
r.content

# 需要传入HTTP Header时，我们传入一个dict作为headers参数
r = requests.get('https://www.douban.com/', headers={'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'})

# 要发送POST请求，只需要把get()方法变成post()，然后传入data参数作为POST请求的数据：
r = requests.post('https://accounts.douban.com/login', data={'form_email': 'abc@example.com', 'form_password': '123456'})

# requests默认使用application/x-www-form-urlencoded对POST数据编码。如果要传递JSON数据，可以直接传入json参数：
params = {'key':'value'}
r = requests.post(url, json=params) # 内部自动序列化为JSON

# 类似的，上传文件需要更复杂的编码格式，但是requests把它简化成files参数
upload_files = {'file': open('report.xls', 'rb')} # 在读取文件时，注意务必使用'rb'即二进制模式读取，这样获取的bytes长度才是文件的长度。
r = requests.post(url, files=upload_files)
# 把post()方法替换为put()，delete()等，就可以以PUT或DELETE方式请求资源

#除了能轻松获取响应内容外，requests对获取HTTP响应的其他信息也非常简单。例如，获取响应头
r.headers
r.headers['Content-Type']

# requests对Cookie做了特殊处理，使得我们不必解析Cookie就可以轻松获取指定的Cookie
r.cookies['ts']
'example_cookie_12345'

# 要在请求中传入Cookie，只需准备一个dict传入cookies参数
cs = {'token': '12345', 'status': 'working'}
r = requests.get(url, cookies=cs, timeout=2.5)
# 要指定超时，传入以秒为单位的timeout参数


# 对于未知编码的bytes，要把它转换成str，需要先“猜测”编码。猜测的方式是先收集各种编码的特征字符，根据特征字符判断，就能有很大概率“猜对”。
# 当然，我们肯定不能从头自己写这个检测编码的功能，这样做费时费力。chardet这个第三方库正好就派上了用场。用它来检测编码，简单易用。
import chardet

# 当我们拿到一个bytes时，就可以对其检测编码
chardet.detect(b'Hello, world!')
{'encoding': 'ascii', 'confidence': 1.0, 'language': ''}
# 注意到还有个confidence字段，表示检测的概率是1.0（即100%）

chardet.detect('离离原上草，一岁一枯荣'.encode('gbk'))
{'encoding': 'GB2312', 'confidence': 0.7407407407407407, 'language': 'Chinese'}
# 注意到GBK是GB2312的超集，两者是同一种编码，检测正确的概率是74%，language字段指出的语言是'Chinese'

chardet.detect('最新の主要ニュース'.encode('euc-jp'))
{'encoding': 'EUC-JP', 'confidence': 0.99, 'language': 'Japanese'}
# 可见，用chardet检测编码，使用简单。获取到编码后，再转换为str，就可以方便后续处理


import psutil
# 用Python来编写脚本简化日常的运维工作是Python的一个重要用途。
# 在Python中获取系统信息的另一个好办法是使用psutil这个第三方模块。顾名思义，psutil = process and system utilities，它不仅可以通过一两行代码实现系统监控，还可以跨平台使用，支持Linux／UNIX／OSX／Windows等，是系统管理员和运维小伙伴不可或缺的必备模块。

psutil.cpu_count() # CPU逻辑数量
psutil.cpu_count(logical=False) # CPU物理核心
psutil.cpu_times() # 统计CPU的用户／系统／空闲时间
# scputimes(user=10963.31, nice=0.0, system=5138.67, idle=356102.45)

# 再实现类似top命令的CPU使用率，每秒刷新一次，累计10次：
for x in range(10):
    print(psutil.cpu_percent(interval=1, percpu=True))
'''
[14.0, 4.0, 4.0, 4.0]
[12.0, 3.0, 4.0, 3.0]
[8.0, 4.0, 3.0, 4.0]
[12.0, 3.0, 3.0, 3.0]
[18.8, 5.1, 5.9, 5.0]
[10.9, 5.0, 4.0, 3.0]
[12.0, 5.0, 4.0, 5.0]
[15.0, 5.0, 4.0, 4.0]
[19.0, 5.0, 5.0, 4.0]
[9.0, 3.0, 2.0, 3.0]
'''

# 使用psutil获取物理内存和交换内存信息，分别使用：
psutil.virtual_memory()
# svmem(total=8589934592, available=2866520064, percent=66.6, used=7201386496, free=216178688, active=3342192640, inactive=2650341376, wired=1208852480)
psutil.swap_memory()
# sswap(total=1073741824, used=150732800, free=923009024, percent=14.0, sin=10705981440, sout=40353792)
# 返回的是字节为单位的整数，可以看到，总内存大小是8589934592 = 8 GB，已用7201386496 = 6.7 GB，使用了66.6%。
# 而交换区大小是1073741824 = 1 GB

# 可以通过psutil获取磁盘分区、磁盘使用率和磁盘IO信息
psutil.disk_partitions() # 磁盘分区信息
# [sdiskpart(device='/dev/disk1', mountpoint='/', fstype='hfs', opts='rw,local,rootfs,dovolfs,journaled,multilabel')]
# 文件格式是HFS，opts中包含rw表示可读写，journaled表示支持日志
psutil.disk_usage('/') # 磁盘使用情况
# 磁盘'/'的总容量是998982549504 = 930 GB，使用了39.1%
psutil.disk_io_counters() # 磁盘IO

# psutil可以获取网络接口和网络连接信息
psutil.net_io_counters() # 获取网络读写字节／包的个数
psutil.net_if_addrs() # 获取网络接口信息
psutil.net_if_stats() # 获取网络接口状态
psutil.net_connections() # 获取当前网络连接信息
# 获取网络连接信息需要root权限

# 通过psutil可以获取到所有进程的详细信息
psutil.pids() # 所有进程ID
p = psutil.Process(3776) # 获取指定进程ID=3776，其实就是当前Python交互环境
p.name() # 进程名称
p.exe() # 进程exe路径
p.cwd() # 进程工作目录
p.cmdline() # 进程启动的命令行
p.ppid() # 父进程ID
p.parent() # 父进程
p.children() # 子进程列表
p.status() # 进程状态
p.username() # 进程用户名
p.create_time() # 进程创建时间
p.terminal() # 进程终端
p.cpu_times() # 进程使用的CPU时间
p.memory_info() # 进程使用的内存
p.open_files() # 进程打开的文件
p.connections() # 进程相关网络连接
p.num_threads() # 进程的线程数量
p.threads() # 所有线程信息
p.terminate() # 结束进程

